package wechat.base.snd

import java.net.URLEncoder
import java.util.Collection
import java.util.Date
import org.eclipse.xtend.lib.annotations.Accessors
import org.json.JSONArray
import org.json.JSONException
import org.json.JSONObject
import wechat.base.snd.encoding.JsonPut
import wechat.base.snd.util.ExecGet
import wechat.base.snd.util.ExecPost

//代表微信号服务号
//@Data
class WCServiceApp{
	@Accessors String grant_type = 'client_credential'
	@Accessors String APP_ID
	@Accessors String SECRET
	String authurl;
	String TOKEN=null
	new (String appid, String secret){
		SECRET = secret
		APP_ID = appid
		authurl = WECHAT_AUTH_URL + APP_ID +'&redirect_uri='
	}
	static String WECHAT_PLATFORM_URL = "https://api.weixin.qq.com";
	static String WECHAT_AUTH_URL = "https://open.weixin.qq.com/connect/oauth2/authorize?appid=";
	
	static String TEMPLATE_DISPATH_MSG_ID = "v_CkyFvYjwXJq525Au4Lv71rslPW5pwcye3vPtBNlTU";
	
	static Long TOKEN_EXPIRATION_TIME = 7200*1000l
	static Date tokenTime = new Date
	def String getToken() { 
		if (((new Date).getTime()-tokenTime.getTime())>=TOKEN_EXPIRATION_TIME||TOKEN==null){
			try{
				println("**********get token*****")
				val tokenUrl = WECHAT_PLATFORM_URL + "/cgi-bin/token?grant_type=" + grant_type + "&appid=" + APP_ID +"&secret=" + SECRET;
				val JSONObject js = new JSONObject(ExecGet::excuteGet(tokenUrl));
				js.getString("access_token")
				this.TOKEN=js.getString("access_token")
				tokenTime = new Date
				println('token='+TOKEN)
			}
			catch(Exception e){
				println("**********Failed to get token*****")
				TOKEN = null
				e.printStackTrace
			}
		}
		TOKEN
	}
	def getApplicationUrl(){
		WECHAT_PLATFORM_URL + "/cgi-bin/message/send?access_token="+ token
	}
	def getApplicationMediaUrl(){
		WECHAT_PLATFORM_URL + "/cgi-bin/media/upload?access_token="+ token
	}
//		https://api.weixin.qq.com/cgi-bin/message/template/send?access_token=ACCESS_TOKEN
	def getApplicationTemplateUrl(){
		WECHAT_PLATFORM_URL + "/cgi-bin/message/template/send?access_token="+ token
	}
	//模板ID: v_CkyFvYjwXJq525Au4Lv71rslPW5pwcye3vPtBNlTU
	//{{first.DATA}}
	//任务名称：{{keyword1.DATA}}
	//相关人员：{{keyword2.DATA}}
	//{{remark.DATA}}
	//你好，微OA有新任务
	//任务名称：报销单等待审批
	//相关人员：「微语科技」晋明会
	//请尽快进行处理	
	def WCTemplateNews createNews(){
		new WCTemplateNews(this)=>[
			withTempId(TEMPLATE_DISPATH_MSG_ID)
		]
	} 
	
	def WCTemplateNews createTemplateNews(){
		new WCTemplateNews(this);
	}
	def String buildAuthConnection(String redirectUrl,String state){
//		URLEncoder::encode(redirectUrl, "utf-8")
		authurl + URLEncoder::encode(redirectUrl, "utf-8") + '&response_type=code&scope=snsapi_base&state='+state+'#wechat_redirect' 
	}
	def String getOpenId(String code) {
		val url= 'https://api.weixin.qq.com/sns/oauth2/access_token?appid='+APP_ID+'&secret='+SECRET+'&code='+code+'&grant_type=authorization_code'
		val jo = new JSONObject(ExecGet::excuteGet(url))
		try {
			jo?.getString('openid')
		} catch (JSONException e) {
			e.printStackTrace();
			null
		}
	}
	
	//https://api.weixin.qq.com/cgi-bin/menu/get?access_token=ACCESS_TOKEN
	//本自定义菜单查询接口可以获取默认菜单和全部个性化菜单信息。
	def String getMenuInfo(){
		val url = 'https://api.weixin.qq.com/cgi-bin/menu/get?access_token='+getToken
		ExecGet::excuteGet(url)
	}
	
//	https://api.weixin.qq.com/cgi-bin/user/get?access_token=ACCESS_TOKEN&next_openid=NEXT_OPENID
//众号可通过本接口来获取帐号的关注者列表，关注者列表由一串OpenID（加密后的微信号，每个用户对每个公众号的OpenID是唯一的）组成。一次拉取调用最多拉取10000个关注者的OpenID，可以通过多次拉取的方式来满足需求。	
	//本自定义菜单查询接口可以获取默认菜单和全部个性化菜单信息。
	def String getAllWeixinUsers(){
		val url = 'https://api.weixin.qq.com/cgi-bin/user/get?access_token='+getToken
		ExecGet::excuteGet(url)
	}
	
	def String getDetailedUserInfo(String openid){
		val url = 'https://api.weixin.qq.com/cgi-bin/user/info?access_token='+getToken+'&openid='+openid+'&lang=zh_CN'
		ExecGet::excuteGet(url)
	}
	
	//创建菜单
	//http请求方式：POST（请使用https协议） https://api.weixin.qq.com/cgi-bin/menu/create?access_token=ACCESS_TOKEN
	def String createMenu(WCMenu menu){
		ExecPost::excuteJsonPost('https://api.weixin.qq.com/cgi-bin/menu/create?access_token='+getToken,menu.build.toString)
	}	
	
	//删除菜单
	//http请求方式：GET（请使用https协议） https://api.weixin.qq.com/cgi-bin/menu/delete?access_token=ACCESS_TOKEN
	def deleteMenu(){
		ExecGet::excuteGet('https://api.weixin.qq.com/cgi-bin/menu/delete?access_token='+getToken)
	}	
}

abstract class WCServiceAppMessage{
	protected WCServiceApp app
	protected JsonPut content
	
	def send2Users(Iterable<String> users){
		for(usr:users){
			content.putObj('touser',usr)
			ExecPost::excuteJsonPost(app.applicationTemplateUrl,content.toString)
		}
	}
	
}
//模板ID: v_CkyFvYjwXJq525Au4Lv71rslPW5pwcye3vPtBNlTU
//{{first.DATA}}
//任务名称：{{keyword1.DATA}}
//相关人员：{{keyword2.DATA}}
//{{remark.DATA}}
//你好，微OA有新任务
//任务名称：报销单等待审批
//相关人员：「微语科技」晋明会
//请尽快进行处理
class WCTemplateNews extends WCServiceAppMessage {
	new (WCServiceApp sa){
		app = sa
		content = new JsonPut
	}
	def withTempId(String tmp_id){
		content.putObj('template_id', tmp_id)
	}
	def withUrl(String url){
		content.putObj('url', url)
	}
	def withAuthUrl(String url, String state){
		withUrl(app.buildAuthConnection(url,state))
	}
	def withData(WCTemplateContent tc){
		content.putObj('data', tc.allContent)
	}
	def getStr(){
		content.toString
	}
}
//{{first.DATA}}
//：{{keyword1.DATA}}
//：{{keyword2.DATA}}
//：{{keyword3.DATA}}
//{{remark.DATA}}
//你好，微OA有新任务
//任务名称：报销单等待审批
//相关人员：「微语科技」晋明会
//请尽快进行处理
class WCTemplateContent{
	JsonPut all= new JsonPut
	def withFirstItem(String data){
		setTemplate('first', data)
	}
	def withKeyword1Item(String data){
		setTemplate('keyword1', data)
	}
	def withKeyword2Item(String data){
		setTemplate('keyword2', data)
	}
	def withKeyword3Item(String data){
		setTemplate('keyword3', data)
	}				
	def withRemarkItem(String data){
		setTemplate('remark', data)	
	}
	def  void setTemplate(String Key, String data) {
		all.putObj(Key, new JsonPut=>[
				putObj('value',data)
//				putObj('color',"#173177")
		])
	}
	def getAllContent(){
		all
	}
}

class WCMenu{
	Collection<WCButton> buttons = newArrayList
	def void withButton(WCButton b){
		buttons.add(b)
	}
	def JSONObject build(){
		new JSONObject=>[
			it.put('button',new JSONArray()=>[
			for (WCButton b:buttons)
				it.put(b.toJson)
			])
		]
	}
	def createBtn(){
		new WCButton
	}
}
class WCButton{
	
	@Accessors String type
	@Accessors String name
	@Accessors String key
	
	JsonPut allbtn= new JsonPut
	
	Collection<WCSubButton> subbuttons = newArrayList
	
	def void withSubButton(WCSubButton b){
		subbuttons.add(b)
	}
	
	def JSONObject toJson(){
		allbtn.put('name',name)
		allbtn.put('type',type)
		allbtn.put('key',key)
		allbtn.put('sub_button',new JSONArray()=>[
			for (WCSubButton b:subbuttons)
				it.put(b.toJson)
		])
	} 
}
class WCSubButton{
	@Accessors String type
	@Accessors String name
	@Accessors String key
	@Accessors String url
	def JSONObject toJson(){
		new JSONObject=>[
			it.put('type',type)
			it.put('name',name)
			it.put('key',key)
			it.put('url',url)
		]
	} 
}

class ErrorMsg{ 
	@Accessors String errcode
	@Accessors String errmsg
	new(JSONObject errorInfo) {
		try {
			errcode = errorInfo.getString("errcode");
			errmsg = errorInfo.getString("errmsg");
		} catch (JSONException e) {
			e.printStackTrace();
		}
	}
}
